昨天講解了 Grid Layout 的基本用法,今天來講最後一個參數 content 的 LazyGridScope 是什麼。
Layout 佈局分為 Column 、Row 、Grid,這類排列的 Composable 最後一行的參數content 可以擺入要呈現的 composable。可以觀察到預設值都是 content: xxxScope.() -> Unit 的形式,不像其他 Compose 是content: () -> Unit 。
Scope 的名稱會對應 Composable 的名,例如 Column 的 Scope 就是ColumnScope ,LazyColumn 是LazyListScope ,而 LazyVerticalGrid 就是 LazyGridScope 。
在 Column 、Row 、Grid 前面加上 Lazy,效果就是以前的 RecyclerView 。Lazy 系列的 Scope 的特點在於,不能直接在 content ={ } 中使用 composable 而是要在DSL 定義的方法內部使用,像是 item() 、items() 等。
關鍵術語:
DSL是 domain-specific language 的縮寫,翻譯成特定領域的語言,也就是block範圍內能使用定義好的function、參數等等。
這裡先舉例 LazyColumn 的DSL function
@Preview(showBackground = true)
@Composable
fun LazyColumnDSL() {
    val intList: List<Int> = listOf(1, 2, 3)
    LazyColumn {
        // 新增1列
        item {
            Text(text = "First item")
        }
        // 新增5列
        items(5) { index ->
            Text(text = "items 5: item =$index")
        }
        // 傳入 list 或 array
        items(intList) { int ->
            Text(text = "items list : item = $int")
        }
        // 傳入 list 或 array 並帶有 index 值
        itemsIndexed(intList) { index, int ->
            Text(text = "items index list : index= $index: item = $int")
        }
    }
}

Grid Layout 的 scope 和 column 一樣也可以用 item 、items(i)、items(List)、items(Array)、itemsIndexed(*List*) 、itemsIndexed(*Array*) 。
Grid Layout 可以很好的計算每一行有多少 items ,但有時候想另外插一行行跨多個欄位的 item 要怎麼做呢?
在 LazyGridScope 中 item() 參數 span 可以做到跨行效果。
fun item(
    key: Any? = null,
    span: (LazyGridItemSpanScope.() -> GridItemSpan)? = null,
    contentType: Any? = null,
    content: @Composable LazyGridItemScope.() -> Unit
)
span = {} 中使用 GridItemSpan(int) 可以單獨計算出該item要行跨多少欄位。
int : 1代表佔用1欄位,數字大於最大欄數效果等同最大欄數 maxLineSpan
this.maxLineSpan : 最大欄數this.maxCurrentLineSpan : 剩餘最大欄數| GridItemSpan(3) | GridItemSpan(this.maxLineSpan) | GridItemSpan(this.maxCurrentLineSpan) | 
|---|---|---|
|  |  |  | 
@Preview
@Composable
fun GridLayout() {
    val list = (1..9).map { it.toString() }
    LazyVerticalGrid(
        //...
        content = {
						//單一個item
						item() {
                Card(
                   //...
                ) {
	                    //...
                }
            }
						// span item
            item(span = { GridItemSpan(this.maxLineSpan) }) {
                Card(
                    modifier = Modifier
                        .padding(4.dp)
                        .fillMaxWidth()
                ) {
                    Text(
                        text = "Span",
                        fontWeight = FontWeight.Bold,
                        fontSize = 30.sp,
                        textAlign = TextAlign.Center,
                        modifier = Modifier.padding(16.dp)
                    )
                }
            }
						// list items
            items(list.size) { index ->
							//...
            }
        }
    )
}
今天介紹了 content 如何使用 Scope,以及專有名詞DSL。
在 grid layout 橫跨多欄可以運用 Span 參數。
今日運動
休息